//
//  String+Extension.swift
//  TuneMate
//
//  Created by 丸子 on 2023/11/23.
//

import UIKit
import Foundation
import CommonCrypto
extension String {
    
    func convertISODateStringToChineseLocalString() -> String? {
        // 创建 DateFormatter 对象来解析时间字符串
        let isoDateFormatter = DateFormatter()
        isoDateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" // 修改这里
        isoDateFormatter.locale = Locale(identifier: "en_US_POSIX")

        // 将时间字符串转换为 Date 对象
        if let date = isoDateFormatter.date(from: self) {
            // 创建用于显示的 DateFormatter 对象
            let displayDateFormatter = DateFormatter()
            displayDateFormatter.dateFormat = "yyyy年MM月dd日 HH:mm"
            displayDateFormatter.timeZone = TimeZone(secondsFromGMT: 0) // 设置为 UTC 时间

            // 将 Date 对象转换为指定格式的字符串
            let displayDateString = displayDateFormatter.string(from: date)
            return displayDateString
        } else {
            print("日期格式无效")
            return nil
        }
    }
    
    func vipExpirationTime() -> String? {
        // 创建 DateFormatter 对象来解析时间字符串
        let isoDateFormatter = DateFormatter()
        isoDateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" // 修改这里
        isoDateFormatter.locale = Locale(identifier: "en_US_POSIX")

        // 将时间字符串转换为 Date 对象
        if let date = isoDateFormatter.date(from: self) {
            // 创建用于显示的 DateFormatter 对象
            let displayDateFormatter = DateFormatter()
            displayDateFormatter.dateFormat = "yyyy年MM月dd日"
            displayDateFormatter.timeZone = TimeZone(secondsFromGMT: 0) // 设置为 UTC 时间

            // 将 Date 对象转换为指定格式的字符串
            let displayDateString = displayDateFormatter.string(from: date)
            return displayDateString
        } else {
            print("日期格式无效")
            return nil
        }
    }
    
    func checkVIPExpiryDate() -> Bool {
        let dateFormatter = ISO8601DateFormatter()
        dateFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
        
        guard let vipEndDate = dateFormatter.date(from: self) else {
            print("Invalid date format")
            return false
        }
        
        let currentDate = Date()
        let hundredYearsFromNow = Calendar.current.date(byAdding: .year, value: 100, to: currentDate)!
        
        if vipEndDate > hundredYearsFromNow {
            print("VIP end time is more than 100 years from now")
            return false
        } else {
            print("VIP end time is within 100 years from now")
            return true
        }
    }
    
    func sizeWithText(font: UIFont, size: CGSize) -> CGSize {
        let attributes = [NSAttributedString.Key.font: font]
        let option = NSStringDrawingOptions.usesLineFragmentOrigin
        let rect: CGRect = self.boundingRect(with: size, options: option, attributes: attributes, context: nil)
        return rect.size;
    }
    
    func textWidth(font:UIFont) -> CGFloat
    {
        let str = self as NSString
        let size = CGSize(width: 200000, height: 100)
        let attributes = [NSAttributedString.Key.font:font]
        let labelSize = str.boundingRect(with: size, options: .usesLineFragmentOrigin, attributes: attributes, context: nil).size
        return labelSize.width
    }
    
    func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [.font: font], context: nil)
        return ceil(boundingBox.height)
    }
    
    func sizeOfString(_ font: UIFont) -> CGSize {
        let size: CGSize = self.size(withAttributes: [NSAttributedString.Key.font: font])
        return size
    }
    
    var isValidURL: Bool {
        let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
        if let match = detector.firstMatch(in: self, options: [], range: NSRange(location: 0, length: self.utf16.count)) {
            // 它是一个链接，如果匹配覆盖整个字符串
            return match.range.length == self.utf16.count
        } else {
            return false
        }
    }
    
    func md5DigestKey() -> String {
        guard !self.isEmpty else {
            return ""
        }
        
        guard let data = self.data(using: .utf8) else {
            return ""
        }
        var result = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
        _ = data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
            CC_MD5(bytes.baseAddress, CC_LONG(data.count), &result)
        }
        let key = result.map { String(format: "%02hhx", $0) }.joined()
        return key
    }
    
    func isChinesePhoneNumber() -> Bool {
        // 定义中国手机号的正则表达式
        let pattern = "^1[3-9]\\d{9}$"
        let regex = try? NSRegularExpression(pattern: pattern)
        
        // 检查手机号是否匹配正则表达式
        let range = NSRange(location: 0, length: self.utf16.count)
        if let match = regex?.firstMatch(in: self, options: [], range: range) {
            return match.range.location != NSNotFound
        }
        return false
    }
    
    func encryptWithAES(key: String, iv: String) -> String? {
        guard let data = self.data(using: .utf8),
              let AESData = AES128operation(operation: CCOperation(kCCEncrypt), data: data, key: key, iv: iv) else {
            return nil
        }
        return AESData.base64EncodedString()
    }
    
    func decryptWithAES(key: String, iv: String) -> String? {
        guard let baseData = Data(base64Encoded: self),
              let AESData = AES128operation(operation: CCOperation(kCCDecrypt), data: baseData, key: key, iv: iv) else {
            return nil
        }
        return String(data: AESData, encoding: .utf8)
    }
    
    private func AES128operation(operation: CCOperation, data: Data, key: String, iv: String) -> Data? {
        let keyLength = kCCKeySizeAES128
        let options = CCOptions(kCCOptionPKCS7Padding)
        
        var keyBytes = [Int8](repeating: 0, count: keyLength + 1)
        key.getCString(&keyBytes, maxLength: keyLength + 1, encoding: .utf8)
        
        var ivBytes = [Int8](repeating: 0, count: kCCBlockSizeAES128 + 1)
        iv.getCString(&ivBytes, maxLength: kCCBlockSizeAES128 + 1, encoding: .utf8)
        
        let dataLength = data.count
        let bufferSize = dataLength + kCCBlockSizeAES128
        var buffer = [UInt8](repeating: 0, count: bufferSize)
        var numBytesEncrypted: size_t = 0
        
        let cryptStatus = CCCrypt(operation,
                                  CCAlgorithm(kCCAlgorithmAES128),
                                  options,
                                  keyBytes, keyLength,
                                  ivBytes,
                                  [UInt8](data), dataLength,
                                  &buffer, bufferSize,
                                  &numBytesEncrypted)
        
        if cryptStatus == kCCSuccess {
            return Data(bytes: buffer, count: numBytesEncrypted)
        } else {
            print("Error: \(cryptStatus)")
            return nil
        }
    }
}

